package com.dtcnet.skmvp.utils;

import android.util.Log;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池管理工具类
 * 功能：
 * 1. 单例模式管理线程池
 * 2. 支持任务去重（根据任务ID）
 * 3. 可选择覆盖已有任务或忽略新任务
 * 4. 提供线程池暂停、恢复、关闭等功能
 * 5. 提供线程池状态查询
 */
public class ThreadPoolUtil {
    private static final String TAG = "ThreadPoolUtil";

    // 核心线程数（CPU核心数）
    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors();
    // 最大线程数（核心线程数的2倍）
    private static final int MAXIMUM_POOL_SIZE = CORE_POOL_SIZE * 2;
    // 非核心线程闲置时超时时间（秒）
    private static final long KEEP_ALIVE_TIME = 60L;
    // 线程池队列容量
    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(128);

    // 线程工厂（设置线程名称）
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "ThreadPoolUtil #" + mCount.getAndIncrement());
        }
    };

    // 线程池实例
    private volatile ThreadPoolExecutor mThreadPoolExecutor;
    // 任务标识集合（用于去重）
    private final Set<String> mTaskIds = new HashSet<>();

    // 单例模式（静态内部类实现）
    private static class Holder {
        private static final ThreadPoolUtil INSTANCE = new ThreadPoolUtil();
    }

    /**
     * 获取线程池工具实例
     */
    public static ThreadPoolUtil getInstance() {
        return Holder.INSTANCE;
    }

    // 私有构造方法
    private ThreadPoolUtil() {
        initThreadPool();
    }

    // 初始化线程池
    private void initThreadPool() {
        mThreadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAXIMUM_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                sPoolWorkQueue,
                sThreadFactory,
                new ThreadPoolExecutor.DiscardOldestPolicy());
    }

    /**
     * @param task 要执行的任务
     */
    public void execute(Runnable task) {
        execute(task, String.valueOf(System.currentTimeMillis()), false);
    }

    /**
     * 执行任务（默认去重策略：忽略重复任务）
     *
     * @param task   要执行的任务
     * @param taskId 任务唯一标识
     */
    public void execute(Runnable task, String taskId) {
        execute(task, taskId, false);
    }

    /**
     * 执行任务
     *
     * @param task            要执行的任务
     * @param taskId          任务唯一标识
     * @param replaceExisting 是否替换已有任务（true-替换，false-忽略）
     */
    public void execute(Runnable task, String taskId, boolean replaceExisting) {
        if (task == null || taskId == null) {
            Log.w(TAG, "Task or taskId is null");
            return;
        }

        synchronized (mTaskIds) {
            if (mTaskIds.contains(taskId)) {
                if (replaceExisting) {
                    // 移除旧任务
                    removeTaskById(taskId);
                    Log.d(TAG, "Replace existing task: " + taskId);
                } else {
                    // 忽略新任务
                    Log.d(TAG, "Task " + taskId + " already exists, skip");
                    return;
                }
            }

            // 添加任务标识
            mTaskIds.add(taskId);
        }

        try {
            mThreadPoolExecutor.execute(new WrappedRunnable(task, taskId));
        } catch (Exception e) {
            synchronized (mTaskIds) {
                mTaskIds.remove(taskId);
            }
            Log.e(TAG, "Execute task error: " + e.getMessage());
        }
    }

    /**
     * 提交任务（默认去重策略：忽略重复任务）
     *
     * @param task   要提交的任务
     * @param taskId 任务唯一标识
     * @return Future对象，可用于取消任务
     */
    public Future<?> submit(Runnable task, String taskId) {
        return submit(task, taskId, false);
    }

    /**
     * 提交任务
     *
     * @param task            要提交的任务
     * @param taskId          任务唯一标识
     * @param replaceExisting 是否替换已有任务（true-替换，false-忽略）
     * @return Future对象，可用于取消任务
     */
    public Future<?> submit(Runnable task, String taskId, boolean replaceExisting) {
        if (task == null || taskId == null) {
            Log.w(TAG, "Task or taskId is null");
            return null;
        }

        synchronized (mTaskIds) {
            if (mTaskIds.contains(taskId)) {
                if (replaceExisting) {
                    // 移除旧任务
                    removeTaskById(taskId);
                    Log.d(TAG, "Replace existing task: " + taskId);
                } else {
                    // 忽略新任务
                    Log.d(TAG, "Task " + taskId + " already exists, skip");
                    return null;
                }
            }

            // 添加任务标识
            mTaskIds.add(taskId);
        }

        try {
            return mThreadPoolExecutor.submit(new WrappedRunnable(task, taskId));
        } catch (Exception e) {
            synchronized (mTaskIds) {
                mTaskIds.remove(taskId);
            }
            Log.e(TAG, "Submit task error: " + e.getMessage());
            return null;
        }
    }

    /**
     * 移除等待中的任务
     *
     * @param taskId 要移除的任务ID
     */
    public void remove(String taskId) {
        if (taskId == null) {
            Log.w(TAG, "TaskId is null");
            return;
        }

        removeTaskById(taskId);
    }

    /**
     * 暂停线程池（停止接受新任务，已存在任务继续执行）
     */
    public void pause() {
        if (mThreadPoolExecutor != null && !mThreadPoolExecutor.isShutdown()) {
            mThreadPoolExecutor.shutdown();
            Log.d(TAG, "Thread pool paused");
        }
    }

    /**
     * 恢复线程池
     */
    public void resume() {
        if (mThreadPoolExecutor == null ||
                mThreadPoolExecutor.isShutdown() ||
                mThreadPoolExecutor.isTerminated()) {

            initThreadPool();
            Log.d(TAG, "Thread pool resumed");
        }
    }

    /**
     * 关闭线程池，等待任务执行完成
     */
    public void shutdown() {
        if (mThreadPoolExecutor != null && !mThreadPoolExecutor.isShutdown()) {
            mThreadPoolExecutor.shutdown();
            synchronized (mTaskIds) {
                mTaskIds.clear();
            }
            Log.d(TAG, "Thread pool shutdown");
        }
    }

    /**
     * 立即关闭线程池，尝试停止所有正在执行的任务
     *
     * @return 返回未执行的任务列表
     */
    public List<Runnable> shutdownNow() {
        if (mThreadPoolExecutor != null && !mThreadPoolExecutor.isShutdown()) {
            synchronized (mTaskIds) {
                mTaskIds.clear();
            }
            Log.d(TAG, "Thread pool shutdown immediately");
            return mThreadPoolExecutor.shutdownNow();
        }
        return null;
    }

    /**
     * 获取当前线程池中活跃线程数
     *
     * @return 活跃线程数
     */
    public int getActiveCount() {
        return mThreadPoolExecutor != null ? mThreadPoolExecutor.getActiveCount() : 0;
    }

    /**
     * 获取当前线程池中任务队列大小
     *
     * @return 任务队列大小
     */
    public int getQueueSize() {
        return mThreadPoolExecutor != null ? mThreadPoolExecutor.getQueue().size() : 0;
    }

    /**
     * 获取线程池状态
     *
     * @return true-已关闭或正在关闭
     */
    public boolean isShutdown() {
        return mThreadPoolExecutor == null || mThreadPoolExecutor.isShutdown();
    }

    /**
     * 获取线程池是否已终止
     *
     * @return true-已终止
     */
    public boolean isTerminated() {
        return mThreadPoolExecutor == null || mThreadPoolExecutor.isTerminated();
    }

    /**
     * 获取当前等待中的任务数量
     *
     * @return 等待任务数量
     */
    public int getPendingTaskCount() {
        synchronized (mTaskIds) {
            return mTaskIds.size();
        }
    }

    // 根据任务ID移除任务（内部方法）
    private void removeTaskById(String taskId) {
        synchronized (mTaskIds) {
            if (!mTaskIds.contains(taskId)) {
                return;
            }

            // 从队列中查找并移除任务
            for (Runnable runnable : mThreadPoolExecutor.getQueue()) {
                if (runnable instanceof WrappedRunnable) {
                    WrappedRunnable wrapped = (WrappedRunnable) runnable;
                    if (taskId.equals(wrapped.getTaskId())) {
                        boolean removed = mThreadPoolExecutor.remove(wrapped);
                        if (removed) {
                            mTaskIds.remove(taskId);
                            Log.d(TAG, "Removed task: " + taskId);
                        }
                        break;
                    }
                }
            }
        }
    }

    // 包装Runnable，用于任务完成后清理任务ID
    private class WrappedRunnable implements Runnable {
        private final Runnable mRunnable;
        private final String mTaskId;

        WrappedRunnable(Runnable runnable, String taskId) {
            this.mRunnable = runnable;
            this.mTaskId = taskId;
        }

        String getTaskId() {
            return mTaskId;
        }

        @Override
        public void run() {
            try {
                mRunnable.run();
            } catch (Exception e) {
                Log.e(TAG, "Task " + mTaskId + " run error: " + e.getMessage());
            } finally {
                synchronized (mTaskIds) {
                    mTaskIds.remove(mTaskId);
                    Log.d(TAG, "Task " + mTaskId + " completed");
                }
            }
        }
    }
}